home *** CD-ROM | disk | FTP | other *** search
/ Maclife 42 / MACLIFE42.ISO.7z / MACLIFE42.ISO / FreeWare200 / 圧縮伸張⁄コード / MacGzip / MacGzip 1.1.2 Source.sea / MacGzip 1.1.2 Source / Mac / MacIO.c < prev    next >
Text File  |  1997-04-01  |  20KB  |  864 lines

  1. /*
  2.  * MacIO.c
  3.  *
  4.  * SPDsoft, August 19, 1995
  5.  * A minimal, non standard Mac IO implementation
  6.  *
  7.  *        Secuential read/write, ascii/binary/macbinary, buffered IO
  8.  *
  9.  * Sept, 1995: Multiple bug fixes.
  10.  * Dec, 1997: Universal Headers
  11.  */
  12.  
  13.  
  14. /*
  15.  * open:
  16.  *            - in MacBinary w mode, actual open is delayed to write/close
  17.  *            - in MacBinary w mode, if file is not MB, fs is used; otherwise
  18.  *                MB name is copied to fs;
  19.  *
  20.  *            - In any w mode, output file must not exist
  21.  */
  22.  
  23. /*
  24.  * fd_table[].new is used only externally
  25.  * You can safely remove all references
  26.  */
  27.  
  28. #include <errno.h>
  29.  
  30. #include <Files.h>
  31. #include <Memory.h>
  32.  
  33. #include "MacBinary.h"
  34. #include "MacIO.h"
  35.  
  36. #include "GzErrors.h"
  37.  
  38. #ifndef MIN
  39. #define MIN(a,b)    ( ((a)<(b)) ? (a) : (b) )
  40. #endif
  41.  
  42. #ifndef PStrCpy
  43. #define    PStrCpy(a,b)        BlockMove((b), (a), *(b) + 1 )
  44. #endif
  45.  
  46. OSType                    DefCreator = 'Gzip';
  47. OSType                    DefType = '¥?¥?¥?¥?';
  48. fildes                    fd_table[MIO_MAX_FILES];
  49. int                        fd_busy[MIO_MAX_FILES] = {    0, 0 };
  50.  
  51. static int        fs_MBflush( int fd );
  52. static int        MyBlockMove( char *src, char *dst, Size n, char c1, char c2 );
  53. static OSErr    OpenPlainFromMB( int fd );
  54. static int        CatInfoToStat (CInfoPBRec *info, struct stat *buf);
  55. static void        SanitizeName (Str255 name);
  56.  
  57. /*
  58.  * these are in gzip.c You can delete them safely (along with the calls)
  59.  * for other applications
  60.  */
  61.  
  62. extern FSSpec    ofs;
  63. extern char        ofname[];
  64. extern int        decompress;
  65. extern OSErr    MakeOFSSpec( FSSpec *fs , Str255 prompt );
  66.  
  67. extern void        SetMMString( const char *fmt, ... );
  68.  
  69. /* end of gzip options
  70.  */
  71. extern int DoError( int ErrType, int ErrSever,const char *, ...);
  72.  
  73. /******************************************************************************
  74.  * functions
  75.  */
  76. #define    ExitErr(a)        { if ((a) != noErr ) { errno = (a); return -1; } }
  77.  
  78. /*
  79.  *    Upon successful completion, the file descriptor is returned.
  80.  *    Otherwise, a value of -1 is returned and errno is set to indicate the
  81.  *    error.
  82.  */
  83. int fs_open( FSSpec *fs, int mode, ...)
  84. {
  85.     int                    i;
  86.     OSErr                err;
  87.     
  88.     
  89.     if (( fs == nil )||(mode & OM_RDWR))/* not supported */
  90.     {
  91.         errno = EFAULT;
  92.         return -1;
  93.     }
  94.     
  95.     for ( i = 0; i< MIO_MAX_FILES; i++ )
  96.         if (fd_busy[i] == 0)
  97.             break;
  98.     
  99.     if ( i == MIO_MAX_FILES )
  100.     {
  101.         errno = ENFILE;
  102.         return -1;
  103.     }
  104.             
  105.     fd_table[i].fsomode = mode;
  106.     
  107.     fd_table[i].mode = MIO_BINARY;
  108.     if ( mode & OM_TEXT ) fd_table[i].mode = MIO_ASCII;
  109.     if ( mode & OM_MACBINARY ) fd_table[i].mode = MIO_MACBIN;
  110.  
  111.     if ( mode & OM_WRONLY )
  112.     {
  113.         fd_table[i].omode    = OM_WRONLY;
  114.         fd_table[i].dref    = 0;
  115.         fd_table[i].rref    = 0;
  116.         fd_table[i].pos        = 0L;
  117.         fd_table[i].len        = 0L;
  118.         fd_table[i].blen    = 0;
  119.         fd_table[i].bstart    = fd_table[i].buffer;
  120.         fd_table[i].deof    = 0;
  121.         fd_table[i].reof    = 0;
  122.  
  123.         fd_table[i].new        = 0;
  124.         fd_table[i].fs        = *fs;
  125.  
  126.         if (fd_table[i].mode != MIO_MACBIN)
  127.         {
  128.             err = FSpCreate(fs, DefCreator, DefType, 0);
  129.             ExitErr(err);
  130.             
  131.             fd_table[i].new        = 1;
  132.             
  133.             if ( noErr != (err = FSpOpenDF(fs, fsWrPerm, &fd_table[i].dref)))
  134.             {
  135.                 fd_table[i].dref = 0;
  136.                 FSpDelete(fs);
  137.                 errno = err;
  138.                 return -1;
  139.             }
  140.         }
  141.         else
  142.         {
  143.             fd_table[i].bstart = (char *)&fd_table[i].header;
  144.         }
  145.         /* we can't open anything in MacBinary Mode */
  146.     }
  147.     else /* OM_RDONLY */
  148.     {
  149.         err = MBHeaderFromFSSpec( fs, &fd_table[i].start, (MBIIHeader *) &fd_table[i].buffer);
  150.         
  151.         ExitErr(err);
  152.                 
  153.         fd_table[i].omode    = OM_RDONLY;
  154.         fd_table[i].dref    = 0;
  155.         fd_table[i].rref    = 0;
  156.         fd_table[i].pos        = 0L;
  157.         fd_table[i].len        = 0L;
  158.         fd_table[i].blen    = 0;
  159.         fd_table[i].bstart    = fd_table[i].buffer;
  160.         fd_table[i].deof    = 0;
  161.         fd_table[i].reof    = 0;
  162.         
  163.         fd_table[i].new        = 0;
  164.         fd_table[i].fs        = *fs;
  165.         
  166.         err = FSpOpenDF(fs, fsRdPerm, &fd_table[i].dref);
  167.         ExitErr(err);
  168.         
  169.         if (fd_table[i].mode == MIO_MACBIN)
  170.         {
  171.             fd_table[i].blen = sizeof(MBIIHeader);    
  172.             fd_table[i].len = sizeof(MBIIHeader) + fd_table[i].start.dlen + fd_table[i].start.rlen;    
  173.             if ( noErr != (err = FSpOpenRF(fs, fsRdPerm, &fd_table[i].rref)))
  174.             {
  175.                 FSClose(fd_table[i].dref); fd_table[i].dref = fd_table[i].rref = 0;
  176.                 errno = err;
  177.                 return -1;
  178.             }
  179.         }
  180.         else
  181.         {
  182.             fd_table[i].len = fd_table[i].start.dlen;
  183.             fd_table[i].start.rlen = 0;
  184.         }
  185.     }
  186.     
  187.     fd_busy[i] = 1;
  188.     return i;
  189. }
  190.  
  191.  
  192. int fs_close(int fd)
  193. {
  194.     ParamBlockRec    pb;
  195.     OSErr            err = noErr;
  196.     long            count = 0;
  197.     Boolean            SetInfo;
  198.     
  199.     if (( 0 > fd ) || ( fd >= MIO_MAX_FILES) || (fd_busy[fd] == 0))
  200.     {
  201.         errno = EBADF;
  202.         return -1;
  203.     }
  204.     
  205.     fd_busy[fd] = 0;
  206.  
  207.     if ( fd_table[fd].omode != OM_RDONLY ) /* flush buffer here */
  208.     {
  209.         if (fd_table[fd].mode == MIO_MACBIN)
  210.         {
  211.             if (fd_table[fd].pos < 128L ) /* it isn't a MacBinary and is too short */
  212.             {
  213.                 err = OpenPlainFromMB( fd );
  214.             }
  215.             else
  216.             {
  217.                 err = (OSErr) fs_MBflush( fd );
  218.                 
  219.                 if ( err > 0 ) err = 0;
  220.                 
  221.                 ExitErr(err);
  222.                 
  223.                 if ( fd_table[fd].dref != 0 )
  224.                     err = SetEOF( fd_table[fd].dref, fd_table[fd].start.dlen );
  225.     
  226.                 if (( fd_table[fd].rref != 0 )&&(err==noErr))
  227.                     err = SetEOF( fd_table[fd].rref, fd_table[fd].start.rlen );
  228.             }
  229.         }
  230.         ExitErr(err);
  231.         
  232.         if (fd_table[fd].mode != MIO_MACBIN)
  233.         {
  234.             if ( fd_table[fd].blen != 0 )
  235.             {
  236.                 count = (long)fd_table[fd].blen;
  237.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  238.                 ExitErr(err);
  239.             }
  240.             err = SetEOF( fd_table[fd].dref, fd_table[fd].pos ); /* ??? */
  241.         }
  242.         ExitErr(err);
  243.     }
  244.     
  245.     SetInfo =    (fd_table[fd].mode == MIO_MACBIN) &&
  246.                 ( fd_table[fd].omode != OM_RDONLY ) &&
  247.                 ( fd_table[fd].dref != 0 ) &&
  248.                 ( fd_table[fd].rref != 0 ) ;
  249.                 
  250.     
  251.     if ( fd_table[fd].dref != 0 )
  252.     {
  253.         if ( fd_table[fd].omode != OM_RDONLY )
  254.         {
  255.             pb.ioParam.ioCompletion = 0;
  256.             pb.ioParam.ioRefNum = fd_table[fd].dref;
  257.             PBFlushFileSync(&pb);
  258.         }
  259.             
  260.         err = FSClose(fd_table[fd].dref);
  261.         fd_table[fd].dref = 0;
  262.     }    
  263.     if (( fd_table[fd].rref != 0 )&&(err==noErr))
  264.     {
  265.         if ( fd_table[fd].omode != OM_RDONLY )
  266.         {
  267.             pb.ioParam.ioCompletion = 0;
  268.             pb.ioParam.ioRefNum = fd_table[fd].rref;
  269.             PBFlushFileSync(&pb);
  270.         }
  271.         err = FSClose(fd_table[fd].rref);
  272.         fd_table[fd].rref = 0;
  273.     }
  274.     
  275.     
  276.     if (SetInfo)
  277.         SetCatInfoFromMBHeader( &fd_table[fd].fs, &fd_table[fd].start, &fd_table[fd].header);
  278.     
  279.     
  280.     ExitErr(err);
  281.     return 0;
  282. }
  283.  
  284. int fs_unlink(FSSpec *fs)
  285. {
  286.     return(FSpDelete(fs));
  287. }
  288.  
  289.  
  290. /*
  291.  * WARNING: This should be size_t, but it is defined as unsigned!
  292.  *
  293.  * fs_read should return always >= 0 or -1
  294.  * On failure, return -1 and set errno to indicate the error
  295.  * We will use mixed errno/OSErr codes (I hope thy will be coherent!)
  296.  */
  297.  
  298. int fs_read(int fd, char *buf, unsigned int n)
  299. {
  300.     OSErr    err = noErr;
  301.     long    count,
  302.             round;
  303.     int        result = 0;
  304.     short    ref;
  305.     
  306.     if (( 0 > fd ) || ( fd >= MIO_MAX_FILES) || (fd_busy[fd] == 0))
  307.     {
  308.         errno = EBADF;
  309.         return -1;
  310.     }
  311.  
  312.     while (( n > 0 ) && (err == noErr))
  313.     {
  314.         if (fd_table[fd].blen == 0)
  315.         {
  316.             if ( fd_table[fd].deof == 0 )
  317.             {
  318.                 ref = fd_table[fd].dref;
  319.             }
  320.             else
  321.             {
  322.                 if ( fd_table[fd].reof == 0 )
  323.                 {
  324.                     ref = fd_table[fd].rref;
  325.                 }
  326.                 else
  327.                 {
  328.                     n = 0;
  329.                     if (result == 0 ) result = -1;
  330.                 }
  331.             }
  332.                 
  333.             if (ref != 0)
  334.             {
  335.                 count = MIO_BUFSIZE;
  336.                 err = FSRead( ref, &count, fd_table[fd].buffer );
  337.  
  338.                 fd_table[fd].blen += (int) count;
  339.                 fd_table[fd].bstart = fd_table[fd].buffer;
  340.  
  341.                 if ( err == eofErr ) /* end of fork reached */
  342.                 {
  343.                     if (fd_table[fd].mode == MIO_MACBIN)
  344.                         if ( 0 != (round = count%128))
  345.                         {
  346.                             count += 128L - round;
  347.                             fd_table[fd].blen += 128 - (int)round;
  348.                         }
  349.                             
  350.                     if ( fd_table[fd].deof == 1 )
  351.                         fd_table[fd].reof = 1;
  352.                     else
  353.                         fd_table[fd].deof = 1;
  354.                         
  355.                     err = noErr;
  356.                 }
  357.             }    
  358.             else
  359.             {    
  360.                 count = 0;
  361.                 err = eofErr;
  362.             }
  363.             errno = err;
  364.         }
  365.         else
  366.         {
  367.             count = MIN( fd_table[fd].blen, (long) n);
  368.             
  369.             if (fd_table[fd].mode == MIO_ASCII)
  370.                 MyBlockMove( fd_table[fd].bstart, buf, (Size) count, 0x0d, 0x0a );
  371.             else
  372.                 BlockMove(    fd_table[fd].bstart, buf, (Size) count );
  373.  
  374.             buf += count;
  375.             fd_table[fd].blen -= (int) count;
  376.             fd_table[fd].pos += count;
  377.             fd_table[fd].bstart += (int) count;
  378.             result += (int) count;
  379.             n -= (int) count;
  380.             
  381.         }
  382.     }
  383.     
  384.     return result;
  385. }
  386.  
  387. /*
  388.  * Por amor al comercio
  389.  * voy a cruzar ese puente
  390.  * Por amor al comercio
  391.  * voy a cuidar ese dolor
  392.  */
  393.  
  394. /*
  395.  * should return n
  396.  * On  failure, return -1 and set errno to indicate the error
  397.  *
  398.  * n == 0 => return 0
  399.  */
  400.  
  401.  
  402.  
  403. int fs_write(int fd, char *buf, unsigned int n)
  404. {
  405.     OSErr    err = noErr;
  406.     long    count;
  407.     int        result = 0;
  408.     
  409.     if (( 0 > fd ) || ( fd >= MIO_MAX_FILES) || (fd_busy[fd] == 0))
  410.     {
  411.         errno = EBADF;
  412.         return -1;
  413.     }
  414.  
  415.     if (fd_table[fd].mode == MIO_MACBIN)
  416.     {
  417.         /* (probably) MacBinary File */
  418.         
  419.         while (( n > 0 ) && (err == noErr))
  420.         {
  421.             if (fd_table[fd].pos < 128L ) /* fill header struct */
  422.             {
  423.                 count                = MIN( (128L - fd_table[fd].pos), (long) n);
  424.                 BlockMove(    buf,    fd_table[fd].bstart, (Size) count );
  425.                 buf                 += count;
  426.                 fd_table[fd].pos    += count;
  427.                 fd_table[fd].bstart    += (int) count;
  428.                 result                += (int) count;
  429.                 n                    -= (int) count;
  430.                 
  431.                 if (fd_table[fd].pos == 128L )
  432.                 {
  433.                     /* validate header */
  434.                     
  435.                     if (PT_File == ValidateMBHeader( &fd_table[fd].start, &fd_table[fd].header, true ))
  436.                     {
  437.                          PStrCpy( fd_table[fd].fs.name, fd_table[fd].start.name );
  438.                          SanitizeName (fd_table[fd].fs.name);
  439.                          
  440.                          
  441. /* macgzip -> */
  442.                         if ( decompress &&    ( ( fd_table[fd].start.rlen != 0 )    ||    ( fd_table[fd].start.dlen != 0 )))
  443.                         {
  444.                             err = MakeOFSSpec( &fd_table[fd].fs , "¥pSave Macintosh File:" );
  445.                             ofs = fd_table[fd].fs;
  446.                             ExitErr(err); /* OJO */
  447.                         }
  448. /* <- macgzip */
  449.                          if ( fd_table[fd].start.dlen == 0 )
  450.                          {
  451.                              fd_table[fd].dref = 0;
  452.                              fd_table[fd].deof = 1;
  453.                          }
  454.                          else
  455.                          {
  456.                              if ( noErr == ( err =
  457.                              FSpCreate( &fd_table[fd].fs, fd_table[fd].start.fcreator, fd_table[fd].start.ftype, 0)))
  458.                             {
  459.                                 fd_table[fd].new        = 1;
  460.                                 err = FSpOpenDF( &fd_table[fd].fs, fsWrPerm, &fd_table[fd].dref);
  461.                             }
  462.                             ExitErr(err);
  463.                             
  464.                             if ( 0 != (fd_table[fd].rdlen = fd_table[fd].start.dlen%128))
  465.                                 fd_table[fd].rdlen = fd_table[fd].start.dlen + (128L - fd_table[fd].rdlen);
  466.                             else
  467.                                 fd_table[fd].rdlen = fd_table[fd].start.dlen;
  468.                          }
  469.  
  470.                          if ( fd_table[fd].start.rlen == 0 )
  471.                          {
  472.                              fd_table[fd].rref = 0;
  473.                              fd_table[fd].reof = 1;
  474.                          }
  475.                          else
  476.                          {
  477.                              FSpCreateResFile( &fd_table[fd].fs, fd_table[fd].start.fcreator, fd_table[fd].start.ftype, 0);
  478.                              if ( noErr == ( err = ResError() ))
  479.                             {    
  480.                                 fd_table[fd].new        = 1;
  481.                                 err = FSpOpenRF( &fd_table[fd].fs, fsWrPerm, &fd_table[fd].rref);
  482.                             }    
  483.                             ExitErr(err);
  484.                                 
  485.                             if ( 0 != (fd_table[fd].rrlen = fd_table[fd].start.rlen%128))
  486.                                 fd_table[fd].rrlen = fd_table[fd].start.rlen + (128L - fd_table[fd].rrlen);
  487.                             else
  488.                                 fd_table[fd].rrlen = fd_table[fd].start.rlen;
  489.  
  490.                          }
  491.                              
  492.                     
  493.                         fd_table[fd].bstart = fd_table[fd].buffer;
  494.                     }
  495.                     else
  496.                     {
  497.                         /* header is not valid */
  498.                         /* treat it (right) like a normal file */
  499.  
  500.                         err = OpenPlainFromMB(fd);
  501.                         break;
  502.                     }
  503.                 }
  504.             }
  505.             else /* write data/resource fork */
  506.             {
  507.                 if (fd_table[fd].blen == MIO_BUFSIZE)
  508.                 {
  509.                     err = fs_MBflush( fd );
  510.                     
  511.                     if ( err > 0 ) err = 0;
  512.                     
  513.                     ExitErr(err);
  514.                     
  515.                     
  516.                 }
  517.                 else
  518.                 {
  519.                     count = MIN( (MIO_BUFSIZE-fd_table[fd].blen), (long) n);
  520.                     BlockMove(    buf, fd_table[fd].bstart, (Size) count );
  521.                     buf += (int) count;
  522.                     
  523.                     fd_table[fd].blen += (int) count;
  524.                     fd_table[fd].pos += count;
  525.                     fd_table[fd].bstart += count;
  526.                     result += (int) count;
  527.                     n -= (int) count;
  528.         
  529.                 }
  530.             }
  531.                 
  532.         } /* while n */
  533.     }
  534.  
  535.     ExitErr(err);
  536.     
  537.     if (fd_table[fd].mode != MIO_MACBIN)
  538.     {
  539.         while (( n > 0 ) && (err == noErr))
  540.         {
  541.             if (fd_table[fd].blen == MIO_BUFSIZE)
  542.             {
  543.                 count = fd_table[fd].blen;
  544.                 
  545.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  546.     
  547.                 fd_table[fd].blen = 0;
  548.                 fd_table[fd].bstart = fd_table[fd].buffer;
  549.             }
  550.             else
  551.             {
  552.                 count = MIN( (MIO_BUFSIZE-fd_table[fd].blen), (long) n);
  553.  
  554.                 if (fd_table[fd].mode == MIO_ASCII)
  555.                     MyBlockMove( buf, fd_table[fd].bstart, (Size) count, 0x0a, 0x0d );
  556.                 else
  557.                     BlockMove( buf, fd_table[fd].bstart, (Size) count );
  558.  
  559.                 buf += (int) count;
  560.  
  561.                 fd_table[fd].blen += (int) count;
  562.                 fd_table[fd].pos += count;
  563.                 fd_table[fd].bstart += count;
  564.                 result += (int) count;
  565.                 n -= (int) count;
  566.     
  567.             }
  568.  
  569.         } /* while n */
  570.     }
  571.     
  572.     ExitErr(err);
  573.     
  574.     return result;
  575. }
  576.  
  577. static int fs_MBflush( int fd )
  578. {
  579.     OSErr        err = noErr;
  580.     long        count = 0, written = 0;
  581.     char        *bstart;
  582.     int            result = 0;
  583.     
  584.     if ( fd_table[fd].blen <= 0 )
  585.         return 0;
  586.                     
  587.     bstart = fd_table[fd].buffer;
  588.     fd_table[fd].bstart = fd_table[fd].buffer;
  589.     
  590.     if ( fd_table[fd].deof == 0 )
  591.     {    
  592.         written = fd_table[fd].pos - 128L - (long) fd_table[fd].blen;
  593.         count = ( fd_table[fd].rdlen - written );
  594.         /*
  595.          * so count is the number of df bytes still not written to file
  596.          */
  597.          
  598.         if ( count <= (long)fd_table[fd].blen )
  599.         {
  600.             fd_table[fd].blen -= (int)count;
  601.             bstart += count;
  602.             result += (int) count;
  603.             
  604.             count -= (fd_table[fd].rdlen - fd_table[fd].start.dlen);
  605.             if ( count > 0 )
  606.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  607.  
  608.             fd_table[fd].deof = 1;
  609.         }
  610.         else
  611.         {
  612.             count = (long)fd_table[fd].blen;
  613.             fd_table[fd].blen -= (int)count;
  614.             bstart += count;
  615.             result += (int) count;
  616.             
  617.             if ( (written + count) > fd_table[fd].start.dlen )
  618.                 count = fd_table[fd].start.dlen - written;
  619.                 
  620.             if ( count > 0 )    
  621.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  622.         }
  623.         
  624.         if ( noErr != err )
  625.             return err;
  626.     }
  627.  
  628.     if ( fd_table[fd].blen <= 0 )
  629.         return result;
  630.  
  631.     if ( fd_table[fd].reof == 0 )
  632.     {        
  633.         written = fd_table[fd].pos - 128L - fd_table[fd].rdlen - (long)fd_table[fd].blen;
  634.         count = ( fd_table[fd].rrlen - written);
  635.         
  636.         if (count <= 0)
  637.         {
  638.             /* skip  clen */
  639.             fd_table[fd].pos += (long)fd_table[fd].blen;
  640.             fd_table[fd].blen = 0;
  641.             return (result + fd_table[fd].blen);
  642.         }
  643.         
  644.         /*
  645.          * so count is the number of df bytes still not written to file
  646.          */
  647.          
  648.         if ( count <= fd_table[fd].blen )
  649.         {
  650.             fd_table[fd].blen -= (int)count;
  651.             result += (int) count;
  652.             
  653.             count -= (fd_table[fd].rrlen - fd_table[fd].start.rlen);
  654.             if ( count > 0 )
  655.                 err = FSWrite( fd_table[fd].rref, &count, bstart );
  656.  
  657.             fd_table[fd].reof = 1;
  658.         }
  659.         else
  660.         {
  661.             count = (long)fd_table[fd].blen;
  662.             fd_table[fd].blen -= (int)count;
  663.             result += (int) count;
  664.             
  665.             if ( (written + count) > fd_table[fd].start.rlen )
  666.                 count = fd_table[fd].start.rlen - written;
  667.                 
  668.             if ( count > 0 )    
  669.                 err = FSWrite( fd_table[fd].rref, &count, bstart );
  670.         }
  671.         
  672.         if ( noErr != err )
  673.             return err;
  674.     }
  675.     
  676.     return result;
  677. }
  678.  
  679.  
  680. /* ejo: swap '¥r' and '¥n' for text files (MPW and CW). Note that we */
  681. /* cannot use '¥r' and '¥n' directly, they have value 0xd and 0xa for */
  682. /* CW and the opposite for MPW (brain damage all over) */
  683.  
  684. static int MyBlockMove( char *src, char *dst, Size n, char c1, char c2 )
  685. {
  686.     char            *tp;
  687.  
  688.     for(    tp = src + n ; src < tp ; src ++ )
  689.             *dst++ = ( *src == c1 ? c2 : *src );
  690.     return 0;
  691. }
  692.  
  693.  
  694. static OSErr    OpenPlainFromMB( int fd )
  695. {
  696.     OSErr        err = noErr;
  697.     long        count = 0;
  698.     
  699.     
  700.     
  701.     if ( fd_table[fd].fsomode & OM_TEXT ) fd_table[fd].mode = MIO_ASCII;
  702.     else fd_table[fd].mode = MIO_BINARY;
  703.     
  704.     
  705.     
  706. /* macgzip -> */
  707.     if ( decompress )
  708.     {
  709.         err = MakeOFSSpec( &fd_table[fd].fs ,
  710.             fd_table[fd].mode == MIO_ASCII ?  "¥pSave text file:" : "¥pSave binary file:" );
  711.         ofs = fd_table[fd].fs;
  712.         ExitErr(err); /* OJO */
  713.         SetMMString( "g%szip (%s) %s", decompress ? "un" : "" ,( fd_table[fd].mode == MIO_ASCII ) ? "ASCII" : "bin" , ofname );
  714.     }
  715. /* <- macgzip */
  716.  
  717.     
  718.     if ( noErr != (err = FSpCreate(&fd_table[fd].fs, DefCreator, DefType, 0)))
  719.         return err;
  720.     
  721.     fd_table[fd].new        = 1;
  722.         
  723.     if ( noErr != (err = FSpOpenDF(&fd_table[fd].fs, fsWrPerm, &fd_table[fd].dref)))
  724.     {
  725.         fd_table[fd].dref = 0;
  726.         FSpDelete(&fd_table[fd].fs);
  727.         return err;
  728.     }
  729.     
  730.     count = (long)fd_table[fd].pos;
  731.     
  732.     if (fd_table[fd].mode == MIO_ASCII)
  733.         MyBlockMove( (char *)&fd_table[fd].header, fd_table[fd].buffer, (Size) count, 0x0a, 0x0d );
  734.     else
  735.         BlockMove( &fd_table[fd].header, fd_table[fd].buffer, (Size) count );
  736.  
  737.     
  738.     fd_table[fd].blen = fd_table[fd].pos;
  739.     fd_table[fd].bstart = fd_table[fd].buffer + fd_table[fd].pos ;
  740.     
  741.     return err;
  742. }
  743.  
  744. /*******************************************************************************
  745.  *
  746.  * CatInfoToStat - fill in stat struct from CInfoPBRec struct.
  747.  *
  748.  * RETURNS: always zero.
  749.  * from stat.c, Written 4 Nov 94, Erling Johansen.
  750.  */
  751.  
  752. /*
  753. About this implementation
  754. -------------------------
  755. The stat information does not fit perfectly good for the Mac, we don't
  756. have things like inodes, links, uid's and guids. This implementation
  757. put the following information in the stat fields:
  758.  
  759. st_mode        - S_IFDIR | 0777 for directories
  760.             - S_IFDIR | 0666 for regular files
  761.             - the w bit is cleared for locked files
  762.             - the x bit is set for applications and MPW tools
  763.             - S_IFCHR | 0777 for stdin, stdout and stderr
  764.  
  765. st_ino        - ioDrDir ID for directories, file number for files
  766.             - 0 for stdin, stdout and stderr
  767. st_dev        - the volume reference number, 0 for stdin, stdout and stderr
  768. st_nlink    - always 1
  769. st_uid        - always 0
  770. st_gid        - always 0
  771. st_size        - ioFlLgLen (size of data fork)
  772.             - 0 for directories and stdin, stdout and stderr
  773. st_atime    - ioDrMdDat for dirs, ioFlMdDat for files (modification date)
  774.             - current calendar time for stdin, stdout and stderr
  775. st_mtime    - same as st_atime
  776. st_ctime    - ioDrCrDat for dirs, ioFlCrDat for files (creation date)
  777.             - current calendar time for stdin, stdout and stderr
  778.             
  779. */
  780.  
  781. int fs_stat(FSSpec *fs, struct stat *buf)
  782. {
  783.     CInfoPBRec info;
  784.     int err;
  785.     
  786.     info.hFileInfo.ioNamePtr                = fs->name;
  787.     info.hFileInfo.ioVRefNum                 = fs->vRefNum;
  788.     info.hFileInfo.ioFDirIndex                = 0;
  789.     info.hFileInfo.ioDirID                    = fs->parID;
  790.  
  791.  
  792.     if ( noErr != ( err = PBGetCatInfoSync( (CInfoPBPtr) &info ) ) )
  793.         errno = err;
  794.     else if (buf == NULL)
  795.         errno = EFAULT;
  796.     else
  797.         return CatInfoToStat (&info, buf);
  798.         
  799.     return -1;
  800. }
  801.  
  802. static int CatInfoToStat (CInfoPBRec *info, struct stat *buf)
  803. {
  804.     buf->st_nlink = 1;
  805.     buf->st_uid = 0;
  806.     buf->st_gid = 0;
  807.     
  808.     if (info->dirInfo.ioFlAttrib & ioDirMask)
  809.     {
  810.         /* a directory */
  811.         buf->st_mode = S_IFDIR | 0777;
  812.         buf->st_ino = info->dirInfo.ioDrDirID;
  813.         buf->st_dev = info->dirInfo.ioVRefNum;
  814.         buf->st_size = 0;
  815.         buf->st_atime = info->dirInfo.ioDrMdDat;
  816.         buf->st_mtime = info->dirInfo.ioDrMdDat;
  817.         buf->st_ctime = info->dirInfo.ioDrCrDat;
  818.     }
  819.     else
  820.     {
  821.         /* a file */
  822.         buf->st_mode = S_IFREG | 0777;
  823.         
  824.         if (info->hFileInfo.ioFlAttrib & 0x01)
  825.             buf->st_mode &=    ~0222;
  826.  
  827.         if (info->hFileInfo.ioFlFndrInfo.fdType != 'APPL'
  828.             && info->hFileInfo.ioFlFndrInfo.fdType != 'MPST')
  829.             buf->st_mode &=    ~0111;
  830.             
  831.         buf->st_ino = info->hFileInfo.ioDirID;
  832.         buf->st_dev = info->hFileInfo.ioVRefNum;
  833.         buf->st_size = info->hFileInfo.ioFlLgLen;
  834.         buf->st_atime = info->hFileInfo.ioFlMdDat;
  835.         buf->st_mtime = info->hFileInfo.ioFlMdDat;
  836.         buf->st_ctime = info->hFileInfo.ioFlCrDat;
  837.         
  838.         buf->st_dsize = info->hFileInfo.ioFlLgLen;
  839.         buf->st_rsize = info->hFileInfo.ioFlRLgLen;
  840.  
  841.         if ( 0 != (buf->st_dsize%128))
  842.                 buf->st_dsize = buf->st_dsize + ( 128 - buf->st_dsize%128 );
  843.         if ( 0 != (buf->st_rsize%128))
  844.                 buf->st_rsize = buf->st_rsize + ( 128 - buf->st_rsize%128 );
  845.         
  846.         buf->st_mbsize = 128 + buf->st_dsize + buf->st_rsize;
  847.  
  848.     }
  849.             
  850.     return 0;
  851. }
  852.  
  853. static void SanitizeName (Str255 name)
  854. {
  855.     int i;
  856.  
  857.     for( i = 1 ; i <= name[0]; i++ )
  858.         if (( name[i] == 0x00 ) ||  ( name[i] == ':' ))
  859.                 name[i] = '-';
  860.                 
  861.     if (( name[0] > 0) && (name[1] == '.'))
  862.         name[1] = '・';
  863. }
  864.